package com.zenghus;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class createWebFile {
	private static String rootPath=System.getProperty("user.dir").replace("\\", "/")+"/src/";//取得项目绝对路径前缀
	private static String jdbcurl="jdbc:mysql://127.0.0.1:3306/webtemplate?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8";
	private static String jdbcuser="root";
	private static String jdbcpassword="123456";
	
	private static String entityurl="main.java.com.zenghus.demo";//entity存放地址
	private static String daourl="main.java.com.zenghus.dao";//到存放地址
	private static String serviceurl="main.java.com.zenghus.service";//service存放地址
	private static String mapperurl="main.java.com.zenghus.mappers";//mapper存放地址
	private static String baseCore="main.java.com.zenghus.jdbccore";//包含BaseDao,BaseService,BaseMapper
	private static String baseCoreImpl="main.java.com.zenghus.jdbccore.impl";//包含BaseDaoImpl,BaseServiceImpl
	private static boolean isCreateService=true;//是否需要创建dao,daoimpl,service,serviceimpl,mapper.java
	
	//base文件名称（已有文件）
	private static String BaseDao="BaseDao";
	private static String BaseDaoImpl="BaseDaoImpl";
	private static String BaseService="BaseService";
	private static String BaseServiceImpl="BaseServiceImpl";
	private static String BaseMapper="BaseMapper";
	
	public static void main(String[] args) throws Exception {
		Map<String, String> map=new HashMap<String, String>();
		map.put("user", "User");//表名，对于实体名称
		for (String string : map.keySet()) {
			String tableName=string;
			String entityName=map.get(string);
			if(createEntity(entityName, tableName)){//创建entity文件
				if(isCreateService){
					createEntityFile(entityName);
				}
				createMapperXml(tableName, entityName);
			}else{
				break;
			}
		}
	}
	
	private static Map<String, String> packagemap=new HashMap<String, String>();
	private static List<Map<String, String>> columnmap=new ArrayList<Map<String,String>>();
	private static Map<String, String> columnCommon=new HashMap<String, String>();
	
	//创建entity
	private static boolean createEntity(String entityName,String tableName) throws Exception{
		packagemap=new HashMap<String, String>();
		columnmap=new ArrayList<Map<String,String>>();
		columnCommon=new HashMap<String, String>();
		
		//获取表的列的注释
		Connection conn1=getConnection();
		Statement stmt1 = conn1.createStatement();
		ResultSet rs1 = stmt1.executeQuery("show full columns from " + tableName);
		while (rs1.next()) {     
			columnCommon.put(rs1.getString("Field"), rs1.getString("Comment"));
		}
		rs1.close();
		stmt1.close();
		conn1.close();
		
		Connection conn = getConnection();
		FileOutputStream out=null;
		try {
			String sql = "select * from "+tableName;
			Statement stmt;
			stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(sql);
			ResultSetMetaData data = rs.getMetaData();
			//创建文件夹
			createDir(rootPath+entityurl.replace(".", "/"));
			//创建文件
			String entity=rootPath+entityurl.replace(".", "/")+"/"+entityName+".java";
			if(createFile(entity)){
				for (int i = 1; i <= data.getColumnCount(); i++) {
					// 对应数据类型的类
					String columnClassName = data.getColumnClassName(i);
					String colutype=columnClassName.substring(columnClassName.lastIndexOf(".")+1,columnClassName.length());
					if(!columnClassName.startsWith("java.lang")){
						packagemap.put(columnClassName, columnClassName);
					}
					// 获得指定列的列名
					String columnName = data.getColumnName(i);
					Map<String, String> m=new HashMap<String, String>();
					m.put("sxname", initcap(columnName));
					m.put("sxtype", colutype);//类型
					m.put("colunm", columnName);//列名
					
					columnmap.add(m);
					// 能否出现在where中
					boolean isSearchable = data.isSearchable(i);
					if(isSearchable==false){
						System.out.println(tableName+"表中的"+columnName+"字段不能出现在where中，请检查！");
						return false;
					}
				}
				//写entity文件
				out=new FileOutputStream(entity);
				PrintStream p=new PrintStream(out);
				StringBuffer sb=new StringBuffer();
				sb.append("package "+entityurl.replaceAll("main.java.","")+";\n\n");
				for (String string : packagemap.keySet()) {
					String importurl=packagemap.get(string);
					sb.append("import "+importurl.replaceAll("main.java.","")+";\n");
				}
				sb.append("\npublic class "+entityName+" {\n\n");
				for (Map<String, String> map : columnmap) {
					sb.append("\tprivate "+map.get("sxtype")+" "+map.get("sxname")+";//"+columnCommon.get(map.get("colunm"))+"\n");
				}
				
				sb.append("\n");
				for (Map<String, String> map : columnmap) {
					sb.append("\tpublic void set" + startA(map.get("sxname")) + "("
		                    + map.get("sxtype") + " " + map.get("sxname")
		                    + "){\r\n");
		            sb.append("\t\tthis." + map.get("sxname") + "=" + map.get("sxname") + ";\r\n");
		            sb.append("\t}\r\n");

		            sb.append("\tpublic " + map.get("sxtype") + " get"
		                    + startA(map.get("sxname")) + "(){\r\n");
		            sb.append("\t\treturn " + map.get("sxname") + ";\r\n");
		            sb.append("\t}\r\n");
				}
				sb.append("}");
				p.print(sb);
				p.close();
			}else{
				return false;
			}
			stmt.close();
			rs.close();
			conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return true;
	}
	
	private static boolean createMapperXml(String tablename,String entityName) throws Exception{
		FileOutputStream out=null;
		//创建文件夹
		createDir(rootPath+mapperurl.replace(".", "/"));
		//创建文件
		String entity=rootPath+mapperurl.replace(".", "/")+"/"+entityName+"Mapper.xml";
		if(createFile(entity)){
			//写entity文件
			out=new FileOutputStream(entity);
			PrintStream p=new PrintStream(out);
			StringBuffer sb=new StringBuffer();
			sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
			sb.append("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n");
			sb.append("<mapper namespace=\""+mapperurl.replaceAll("main.java.","")+"."+entityName+"Mapper\" > \n");
			sb.append("<resultMap id=\"BaseResultMap\" type=\""+entityurl.replaceAll("main.java.","")+"."+entityName+"\" >\n");
			String colunms="";
			String cowhere="";
			String values="";
			String inserts="";
			String updates="";
			for (Map<String, String> map : columnmap) {
				sb.append("\t<result column=\""+map.get("colunm")+"\" property=\""+map.get("sxname")+"\"/>\n");
				colunms+="`"+map.get("colunm")+"`,";
				cowhere+="<if test=\""+map.get("sxname")+" != null\" >\n\t\t\t and `"+map.get("colunm")+"` =  #{"+map.get("sxname")+"}\n\t\t</if>\n\t\t";
				values+="#{"+map.get("sxname")+"},";
				inserts+="`"+map.get("colunm")+"`,";
				if(columnmap.get(0)!=map){
					updates+="`"+map.get("colunm")+"`="+"#{"+map.get("sxname")+"},";
				}
			}
			sb.append("</resultMap>\n\n");
			
			sb.append("<sql id=\"Example_Where_Clause\">\n \twhere 1=1 \n\t<trim  suffixOverrides=\",\" >\n\t\t");
			sb.append(cowhere);
			sb.append("\t</trim>\n</sql>\n\n");
			
			sb.append("<!-- 插入记录 -->\n<insert id=\"add\" parameterType=\"Object\" >\n"
					+ "<selectKey resultType=\"java.lang.Integer\" order=\"AFTER\" keyProperty=\"id\">\n\tSELECT LAST_INSERT_ID()\n\t</selectKey>\n\t\t"
					+ "insert into "+tablename+"("+inserts.substring(0, inserts.length()-1)+")\n\t\tvalues("+values.substring(0, values.length()-1)+")\n</insert>\n");
			
			sb.append("\n<!-- 删除记录 -->\n<delete id=\"delete\" parameterType=\"Object\">\n\tdelete 	 from "+tablename+" where id = #{id}\n</delete>\n");
			
			sb.append("\n<select id=\"queryById\"  resultMap=\"BaseResultMap\" parameterType=\"Object\">\n\t"
					+ "select * from "+tablename+" where id = #{id}"
					+ "\n</select>\n");
			
			
			sb.append("\n<select id=\"queryByList\" resultMap=\"BaseResultMap\"  parameterType=\"Object\">\n\t"
					+ "select * from "+tablename+"  <include refid=\"Example_Where_Clause\"/>"
					+ "\n</select>\n");
			
			
			sb.append("\n<!-- 根据id，修改记录-->  "
					+ "\n<update id=\"update\" parameterType=\"Object\" >\n\t"
					+ "update "+tablename+" set "+updates.substring(0, updates.length()-1)+" \n\t where id=#{"+columnmap.get(0).get("colunm")+"}"
					+ "\n</update>\n");
			
			sb.append("</mapper>");
			p.append(sb);
			out.close();
			p.close();
		}else{
			return false;
		}
		
		return true;
	}
	
	/**
	 * 创建dao,daoimpl,service,serviceimpl,mapper
	 * @return
	 */
	private static boolean createEntityFile(String entityName) throws Exception{
		//写entity文件
		FileOutputStream out = null;
		PrintStream p=null;
		try {
			String fileurl="";
			String filename="";
			String entity="";
			String extendName="";
			String impladd="";
			String methodadd="";
			StringBuffer sb=new StringBuffer();
			boolean isimpl=false;
			for(int i=0;i<5;i++){
				if(i==0){//dao
					fileurl=daourl;
					filename=entityName+"Dao";
					extendName=BaseDao;
				}else if(i==1){//service
					fileurl=serviceurl;
					filename=entityName+"Service";
					extendName=BaseService;
				}else if(i==2){//mapper
					fileurl=mapperurl;
					filename=entityName+"Mapper";
					extendName=BaseMapper;
				}else if(i==3){
					isimpl=true;
					fileurl=daourl+".impl";
					filename=entityName+"DaoImpl";
					extendName=BaseDaoImpl;
					impladd="import "+baseCore.replaceAll("main.java.","")+"."+BaseMapper+";\nimport "+baseCoreImpl.replaceAll("main.java.","")+"."+BaseDaoImpl+";\nimport "+mapperurl.replaceAll("main.java.","")+"."+entityName+"Mapper"+";\n";
					methodadd="\t@Autowired\n\tprivate "+entityName+"Mapper mapper;\n\n\tpublic "+BaseMapper+" getMapper() {\n\t\treturn mapper;\n\t}";
				}else if(i==4){
					isimpl=true;
					fileurl=serviceurl+".impl";
					filename=entityName+"ServiceImpl";
					extendName=BaseServiceImpl;
					
					impladd="import "+baseCore.replaceAll("main.java.","")+"."+BaseDao+";\nimport "+baseCoreImpl.replaceAll("main.java.","")+"."+BaseServiceImpl+";\nimport "+serviceurl.replaceAll("main.java.","")+"."+entityName+"Service"+";\n";
					methodadd="\t@Autowired\n\tprivate "+entityName+"Dao dao;\n\n\tpublic "+BaseDao+" getDao() {\n\t\treturn dao;\n\t}";
				}
				
				//创建文件夹
				createDir(rootPath+fileurl.replace(".", "/"));
				//创建文件
				entity=rootPath+fileurl.replace(".", "/")+"/"+filename+".java";
				if(createFile(entity)){
					out = new FileOutputStream(entity);
					p=new PrintStream(out);
					sb=new StringBuffer();
					if(fileurl.startsWith("main.java.")){
						fileurl=fileurl.replaceAll("main.java.","");
					}
					sb.append("package "+fileurl+";\n\n");
					sb.append("import org.springframework.stereotype.Service;\n");
					if(isimpl==false){
						sb.append("import "+baseCore.replaceAll("main.java.","")+"."+extendName+";\n\n\n");
						sb.append("@Service\n");
						sb.append("public interface "+filename+" extends "+extendName+"{");
					}else{
						sb.append("import org.springframework.beans.factory.annotation.Autowired;\n");
						sb.append("import "+daourl.replaceAll("main.java.","")+"."+entityName+"Dao;\n");
						sb.append(impladd);
						sb.append("\n@Service\n");
						sb.append("public class "+filename+" extends "+extendName+" implements "+filename.replace("Impl", "")+"{\n\n");
						sb.append(methodadd);
					}
					
					sb.append("\n\n}");
					p.print(sb);
				}else{
					return false;
				}
				out.close();
				p.close();
			}
			System.out.println("dao,daoimpl,service,serviceimpl,mapper成功："+entityName);
			return true;
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("dao,daoimpl,service,serviceimpl,mapper失败："+entityName);
			return false;
		}
	}
	
	/**
    * 把输入字符串的首字母改成大写
    * 
    * @param str
    * @return
    */
    private static String initcap(String str) {
    	String result="";
        String[] chs = str.split("_");
        for (int i=0;i<chs.length;i++) {
        	String string=chs[i];
        	char[] ch=string.toCharArray();
        	if(i!=0){
        		if (ch[0] >= 'a' && ch[0] <= 'z') {
        			ch[0] = (char) (ch[0]-32);
        		}
        	}
        	result+=new String(ch);
		}
        return result;
    }
    
    /**
     * 第一个字符大写
     * @param str
     * @return
     */
    private static String startA(String str) {
    	char[] ch=str.toCharArray();
    		if (ch[0] >= 'a' && ch[0] <= 'z') {
    			ch[0] = (char) (ch[0]-32);
    		}
    	str=new String(ch);
    	return str;
    }
	
	// 创建单个文件
	public static boolean createFile(String filePath) {
		File file = new File(filePath);
		if (file.exists()) {// 判断文件是否存在
			/*System.out.println("目标文件已存在" + filePath);
			return false;*/
			file.delete();
			file = new File(filePath);
			return true;
		}
		if (filePath.endsWith(File.separator)) {// 判断文件是否为目录
			System.out.println("目标文件不能为目录！"+filePath);
			return false;
		}
		if (!file.getParentFile().exists()) {// 判断目标文件所在的目录是否存在
			// 如果目标文件所在的文件夹不存在，则创建父文件夹
			System.out.println("目标文件所在目录不存在，准备创建它！");
			if (!file.getParentFile().mkdirs()) {// 判断创建目录是否成功
				System.out.println("创建目标文件所在的目录失败！"+filePath);
				return false;
			}
		}
		try {
			if (file.createNewFile()) {// 创建目标文件
				System.out.println("创建文件成功:" + filePath);
				return true;
			} else {
				System.out.println("创建文件失败！"+filePath);
				return false;
			}
		} catch (IOException e) {// 捕获异常
			e.printStackTrace();
			System.out.println("创建文件失败！" + e.getMessage());
			return false;
		}
	}
	
	
	// 创建目录
	public static boolean createDir(String destDirName) {
		File dir = new File(destDirName);
		if (dir.exists()) {// 判断目录是否存在
			System.out.println("创建目录失败，目标目录已存在！"+destDirName);
			return false;
		}
		if (!destDirName.endsWith(File.separator)) {// 结尾是否以"/"结束
			destDirName = destDirName + File.separator;
		}
		if (dir.mkdirs()) {// 创建目标目录
			System.out.println("创建目录成功！" + destDirName);
			return true;
		} else {
			System.out.println("创建目录失败！"+destDirName);
			return false;
		}
	}
	
	/**
	 * 获取jdbc
	 * @return
	 */
	public static Connection getConnection() {
		Connection conn = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			String url = jdbcurl;
			String user = jdbcuser;
			String pass = jdbcpassword;
			conn = DriverManager.getConnection(url, user, pass);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return conn;
	}
}